Flux CD用の AWS CloudFormation コントローラーがリリース(プレビュー)されました
「Flux でCloudFormationをデプロイ! CloudFormationでもPull型のGitOpsが始まる!?」
Fluxを使用して、CloudFormationをデプロイできるようになりました。
以下のアップデートの紹介ブログです。
Introducing the AWS CloudFormation Template Sync Controller for Flux
Fluxとは
Gitリポジトリで宣言された状態とKubernetesクラスタの状態を同期するツールです。
類似のツールとしては、Argo CDなどがあげられます。
CDに使われるツールでGitリポジトリ上のコードが変更されたら、自動的にクラスターにデプロイすることができます。
「GitHub ActionsやAWSのCodeシリーズなどのCI/CDツールと何が違うの?」と思う方もいるかもしれません。
FluxやArgo CDなどはGitOpsツール(Pull型)と言われます。(Github Actions等はCIOps(Push型))
リポジトリへのPushをトリガーにするわけではなく、FluxがKubernetesクラスター上でGitリポジトリの変更をポーリング(Pull)して変更があったら反映(デプロイ)するためです。
CIOpsとGitOpsについては、以下の記事の説明が分かりやすいです。
CIOpsとGitOpsの話 - inductor's blog
何が嬉しい?
CloudFormationをFluxで管理できることで、以下のようなメリットがあります。
- 正しい設定にリソースを保ちやすい
- KubernetesとCloudFormationのCDを1つのツールで行える
- CD用の権限をAWS外部に渡す必要がない
正しい設定にリソースを保ちやすい
Push型のCIOpsでは、CloudFormationが実行されるのはトリガー時(特定ブランチへのPush等)だけです。
もし手動でAWSリソースが変更された場合、次のPushまではAWSリソースとコードの状態が一致しません。
しかし、Pull型のGitOpsは定期的にGitリポジトリをPollingします。
Gitリポジトリの状態を正として、リソースに差分があればGitリポジトリで定義されている状態に変更します。
リソースを正しい設定状態に保ちやすいのがメリットだと思います。
KubernetesとCloudFormationのCDを1つのツールで行える
既にFluxを使用していてかつ、CloudFormationも使っている場合、CloudFormation用にCDの仕組みを作らなくても、FluxにCDを統一できるメリットもあります。
CD用の権限をAWS外部に渡す必要がない
Pull型のGitOpsのメリットとして、認証情報を外部に渡す必要がないというのも挙げられます。
Github ActionsやCircle CI等でCloudFormationのデプロイを行う場合は、AWS外部に認証情報を渡す必要がありました。
EKSに権限を渡せばいいので、AWS外部に認証情報を渡す必要がありません。 (Codeシリーズだったら、AWS外部に渡さないでCloudFormationデプロイは可能ですが。)
やってみる
前提条件
以下をローカルPC上で使用できるようにしておく必要があります。
構成図
FluxのCloudFormation Controllerを使用して、CloudFormation Stackを作成してみます。
CloudFormationでは、Parameter Storeを作成します。
フォルダ構成
最終的なフォルダ構成を紹介します。
CodeCommitを2つ使用します。(手順中のサンプルリソース作成用CloudFormationでデプロイします)
リポジトリ名 | 概要 |
---|---|
my-flux-configuration | Fluxマニフェストファイル保存用 |
my-cloudformation-templates | CloudFormationテンプレートファイル保存用 |
# my-flux-configuration リポジトリ $ tree my-flux-configuration/ my-flux-configuration ├── cfn-controller-source.yaml # cfn controllerのGitリポジトリ設定 ├── cfn-controller.yaml # cfn controllerデプロイ ├── cfn-stack.yaml # cfn stackデプロイ ├── cfn-templates-repo.yaml # my-cloudformation-templatesのGitリポジトリ設定 └── flux-system ├── gotk-components.yaml ├── gotk-sync.yaml └── kustomization.yaml
# my-cloudformation-templates リポジトリ $ tree my-cloudformation-templates/ my-cloudformation-templates └── template.yaml # デプロイするCloudFormationテンプレート
eksctlでクラスター作成
$ eksctl create cluster \ --name flux-cfn-sample \ --region ap-northeast-1 \ --node-type t3.small \ --nodes 2
FluxのCloudFormationコントローラーがリソースを操作できるように権限を付与します。
本来なら必要な権限に絞るべきですが、検証のためPowerUserAccessを与えます。
$ eksctl utils associate-iam-oidc-provider --cluster flux-cfn-sample --approve $ eksctl create iamserviceaccount \ --cluster flux-cfn-sample \ --namespace flux-system \ --name cfn-controller \ --role-only \ --role-name "AWSCloudFormationControllerFluxIRSARole" \ --attach-policy-arn arn:aws:iam::aws:policy/PowerUserAccess \ --approve
Fluxの設定ファイル保存用のCodeCommit等の準備
Fluxの設定ファイルやCloudFormationテンプレート等を置くCodeCommitやS3バケットを用意します。
サンプルのCloudFormationを使用して、必要なリソースを作成します。
Fluxのインストール
作成したクラスターでFluxを実行可能か確認します。
問題なければ以下のような出力があります。
$ flux check --pre ► checking prerequisites ✔ Kubernetes 1.25.3 >=1.20.6-0 ✔ prerequisites checks passed
リポジトリはサンプルCloudFormationで作成されるCodeCommitを使用します。
flux-git
というIAMユーザーが作成されているため、CodeCommit認証情報を生成してflux bootstrap
を行います。
flux bootstrap git \ --url=https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/my-flux-configuration \ --branch=main \ --username=<my-username> \ --password=<my-password> \ --token-auth=true
bootstrapを実施したことで、EKSにはFluxのインストールおよび、CodeCommitにFluxを使用するために必要なファイルがpushされました。
CloudFormationコントローラリポジトリをFluxに登録する
CloudFormationコントローラーをFluxで使用できるようにするために、リポジトリをFluxに登録します。
任意のディレクトリにFluxのCodeCommitリポジトリをCloneします。
git clone codecommit::ap-northeast-1://my-flux-configuration
以下のファイルを作成して、CodeCommitにPushします。
apiVersion: source.toolkit.fluxcd.io/v1beta2 kind: GitRepository metadata: name: aws-cloudformation-controller-for-flux namespace: flux-system spec: interval: 1h timeout: 60s ref: branch: main url: https://github.com/awslabs/aws-cloudformation-controller-for-flux
git add . git commit -m "add: cfn controller repo" git push origin HEAD
Pushまでできたら、以下のコマンドを実行してFluxがリポジトリに正常に接続できることを確認します。
$ flux reconcile source git flux-system $ flux reconcile source git aws-cloudformation-controller-for-flux
Fluxを使用してCloudFormationコントローラーをデプロイする
CloudFormationコントローラーをデプロイします。
以下のファイルを用意して、CodeCommitにPushします。
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2 kind: Kustomization metadata: name: aws-cloudformation-controller-for-flux namespace: flux-system spec: interval: 5m path: ./config/default prune: true wait: true timeout: 5m sourceRef: kind: GitRepository name: aws-cloudformation-controller-for-flux patches: - patch: | apiVersion: v1 kind: ServiceAccount metadata: name: cfn-controller annotations: eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/AWSCloudFormationControllerFluxIRSARole # AWSアカウントIDを書き換える target: kind: ServiceAccount name: cfn-controller - patch: | apiVersion: apps/v1 kind: Deployment metadata: name: cfn-controller spec: template: spec: containers: - name: manager env: - name: AWS_REGION value: "ap-northeast-1" - name: TEMPLATE_BUCKET value: "<バケット名>" # サンプルCFnで作成したバケット名 target: kind: Deployment name: cfn-controller
git add . git commit -m "add: cfn controller" git push origin HEAD
以下のコマンドでデプロイを確認します。
$ flux reconcile source git flux-system $ flux reconcile kustomization aws-cloudformation-controller-for-flux $ kubectl rollout status deployment/cfn-controller -n flux-system $ kubectl logs deployment/cfn-controller -n flux-system
CloudFormationコントローラーのFlux通知の有効化
CloudFormationコントローラーはサードパーティーコントローラーのため、以下の設定を追加して通知を有効化します。
apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - gotk-components.yaml - gotk-sync.yaml patches: - patch: | - op: add path: /spec/versions/0/schema/openAPIV3Schema/properties/spec/properties/eventSources/items/properties/kind/enum/- value: CloudFormationStack - op: add path: /spec/versions/1/schema/openAPIV3Schema/properties/spec/properties/eventSources/items/properties/kind/enum/- value: CloudFormationStack target: kind: CustomResourceDefinition name: alerts.notification.toolkit.fluxcd.io - patch: | - op: add path: /spec/versions/0/schema/openAPIV3Schema/properties/spec/properties/resources/items/properties/kind/enum/- value: CloudFormationStack - op: add path: /spec/versions/1/schema/openAPIV3Schema/properties/spec/properties/resources/items/properties/kind/enum/- value: CloudFormationStack target: kind: CustomResourceDefinition name: receivers.notification.toolkit.fluxcd.io - patch: | - op: add path: /rules/- value: apiGroups: [ 'cloudformation.contrib.fluxcd.io' ] resources: [ '*' ] verbs: [ '*' ] target: kind: ClusterRole name: crd-controller-flux-system
CloudFormationテンプレートリポジトリにテンプレートファイルをPush
CloudFormationテンプレートファイル用のリポジトリにテンプレートファイルをPushします。
このテンプレートファイルがFluxによって、デプロイされます。
$ git clone codecommit::ap-northeast-1://my-cloudformation-templates $ cd my-cloudformation-templates $ touch template.yaml
Resources: SampleResource: Type: AWS::SSM::Parameter Properties: Type: String Value: "Hello World"
$ git add . $ git commit -m "add: temaplte file" $ git push origin HEAD
CloudFormation用のCodeCommitリポジトリと接続
FluxがCloudFormation用のCodeCommitリポジトリの内容を見れるように設定を行います。
bootstrap時に使用したCodeCommitの認証情報をSecretに登録します。
$ CODECOMMIT_USERNAME="<CodeCommitユーザー名>" $ CODECOMMIT_PASSWORD="<CodeCommitパスワード>" $ flux create secret git cfn-template-repo-auth \ --url=https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/my-cloudformation-templates \ --username=$CODECOMMIT_USERNAME \ --password=$CODECOMMIT_PASSWORD
fluxの設定リポジトリに移動して、以下のファイルを作成します。
$ cd my-flux-configuration $ touch cfn-templates-repo.yaml cfn-stack.yaml
cfn-templates-repo.yaml
はCloudFormation用のCodeCommitリポジトリを登録します。
apiVersion: source.toolkit.fluxcd.io/v1beta2 kind: GitRepository metadata: name: my-cfn-templates-repo namespace: flux-system spec: url: https://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/my-cloudformation-templates interval: 5m ref: branch: main secretRef: name: cfn-template-repo-auth
cfn-stack.yaml
では、デプロイするCloudFormation Stackの設定を行います。
このファイルで、同期の間隔やStack名などを定義します。
apiVersion: cloudformation.contrib.fluxcd.io/v1alpha1 kind: CloudFormationStack metadata: name: my-cfn-stack namespace: flux-system spec: stackName: my-cfn-stack-deployed-by-flux templatePath: ./template.yaml sourceRef: kind: GitRepository name: my-cfn-templates-repo interval: 1h retryInterval: 5m destroyStackOnDeletion: true
ファイルの用意ができたら、リポジトリにPushします。
$ git add . $ git commit -m "add: cfn stack file" $ git push origin HEAD
動作確認: CloudFormation Stackデプロイ確認
先ほどのファイルのPushができたら、自動的にCloudFormation Stackが作成されます。
まずは、kubectl
コマンドで確認してみます。
デプロイが成功していれば、以下のような出力を確認できます。
$ kubectl describe cfnstack my-cfn-stack --namespace flux-system Name: my-cfn-stack Namespace: flux-system Labels: kustomize.toolkit.fluxcd.io/name=flux-system kustomize.toolkit.fluxcd.io/namespace=flux-system Annotations: <none> API Version: cloudformation.contrib.fluxcd.io/v1alpha1 Kind: CloudFormationStack Metadata: Creation Timestamp: 2023-05-10T08:43:54Z Finalizers: finalizers.cloudformation.contrib.fluxcd.io Generation: 1 Managed Fields: API Version: cloudformation.contrib.fluxcd.io/v1alpha1 Fields Type: FieldsV1 # 省略
マネジメントコンソールからも確認してみましょう。
Flux CDで定義したスタックmy-cfn-stack-deployed-by-flux
が確認できます。
CloudFormationを変更して、CodeCommitにPushで自動的にデプロイされるか確認します。
Parameter StoreのValueをHello World
からHello Flux CloudFormation Controller
に変更しました。
commitして、CodeCommitにPushしました。
$ git diff diff --git a/template.yaml b/template.yaml index 51b5e79..752a177 100644 --- a/template.yaml +++ b/template.yaml @@ -3,4 +3,4 @@ Resources: Type: AWS::SSM::Parameter Properties: Type: String - Value: "Hello World" + Value: "Hello Flux Cloudformation Controller"
少し待つと変更した値にパラメータストアの値が変わっていることを確認できました。
クリーンアップ
EKSクラスターを削除します。
$ eksctl delete cluster --name=flux-cfn-sample
まとめ
Terraform用のControllerはあったみたいですが、CloudFormationもきましたね。
How to GitOps Your Terraform | Flux
EKSの運用が必要になるので少し敷居は高いと思いますが、CloudFormationでもGitOpsが可能になるのは激アツだと思いました。
以上、AWS事業本部の佐藤(@chari7311)でした。